﻿#include<algorithm>
#include"./Component.hpp"


namespace MMF
{

    MMFComponentBase::MMFComponentBase(const MMFCtx& ctx, MMFDevice* device, const std::string& name)
        : mCtx(ctx)
        , mDevice(device)
    {
        mInfo.mName = name;
    }

    MMFComponentBase::~MMFComponentBase()
    {

    }

    uint32_t MMFComponentBase::InPortNum()
    {
        return (uint32_t)mDevice->mInType.size();
    }

    uint32_t MMFComponentBase::OutPortNum()
    {
        return (uint32_t)mDevice->mOutType.size();
    }

    MMFDataType MMFComponentBase::GetInDataType(uint32_t portIndex)
    {
        if (InPortNum() < portIndex)
            return MMFDataType::ERR;

        return mDevice->mInType[portIndex];
    }

    std::shared_ptr<MMFPort> MMFComponentBase::GetInPort(uint32_t portIndex)
    {
        return mInPorts[portIndex];
    }

    MMFDataType MMFComponentBase::GetOutDataType(uint32_t portIndex)
    {
        if (OutPortNum() < portIndex)
            return MMFDataType::ERR;

        return mDevice->mOutType[portIndex];
    }

    MMFComponentErr MMFComponentBase::AddConnection(uint32_t outPortIdx, std::shared_ptr<MMFPort>& port)
    {
        //参数不合法
        if (outPortIdx >= OutPortNum() || port == nullptr)
            return MMFComponentErr::OUT_PORT_ERR;

        //要加入得端口目前已经有链接
        if (port->mParent != nullptr || port->mIndexOfParent != -1)
            return MMFComponentErr::PORT_IS_CONNECTED;

        //判断要链接进来得端口得数据类型是否与输出端口一致
        if (
            port->mOwner->mDevice->mInType[port->mIndex] != 
            mDevice->mOutType[outPortIdx]
            )
            return MMFComponentErr::PORT_DATA_TYPE_ERR;

        //添加链接
        std::map<uint32_t, std::vector<std::shared_ptr<MMFPort>>>::iterator find = mOutPorts.find(outPortIdx);
        if (find != mOutPorts.end())        //该输出端口没有链接任何输入端口
        {
            auto iter = std::find(find->second.begin(), find->second.end(), port);
            if (iter != find->second.end())
                return MMFComponentErr::PORT_IS_CONNECTED;
            else 
                find->second.push_back(port);
        }
        else                                //已经有链接了
        {
            std::vector<std::shared_ptr<MMFPort>> ports;
            ports.push_back(port);
            mOutPorts.emplace(outPortIdx, ports);
        }

        //链接输出端口输入端口
        port->mIndexOfParent = outPortIdx;
        port->mParent = this;

        return MMFComponentErr::OK;
    } 


    MMFComponentErr MMFComponentBase::DeleteConnection(uint32_t outPortIdx, std::shared_ptr<MMFPort>& port)
    {
        //参数不合法
        if (outPortIdx >= OutPortNum() || port == nullptr)
            return MMFComponentErr::OUT_PORT_ERR;

        if (port->mParent == nullptr && port->mIndexOfParent == -1)
            return MMFComponentErr::PORT_IS_DUSCONNECTED;

        //该输出端口还没有链接任何输入端口
        std::map<uint32_t, std::vector<std::shared_ptr<MMFPort>>>::iterator find = mOutPorts.find(outPortIdx);
        if (find != mOutPorts.end())
            return MMFComponentErr::PORT_IS_DUSCONNECTED;

        //没找到输入端口在接在本输出端口上
        auto iter = std::find(find->second.begin(), find->second.end(), port);
        if (iter == find->second.end())
            return MMFComponentErr::PORT_IS_DUSCONNECTED;

        //删除端口
        find->second.erase(iter);

        //断开链接
        port->mParent = nullptr;
        port->mIndexOfParent = -1;

        return MMFComponentErr::OK;
    }


    const MMFComponentInfo& MMFComponentBase::Info()
    {
        return mInfo;
    }
}
